package com.csair.seam.infrastructure.job;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.csair.seam.domain.model.entity.EquipUserAlterNotice;
import com.csair.seam.domain.model.entity.Inventory;
import com.csair.seam.domain.service.IEhomeService;
import com.csair.seam.domain.service.IEquipService;
import com.csair.seam.domain.service.IFaAssetService;
import com.csair.seam.domain.service.IFaFinanceService;
import com.csair.seam.domain.service.IFaMatchService;
import com.csair.seam.domain.service.IInventoryService;
import com.csair.seam.infrastructure.ehome.NoticeResult;
import com.csair.seam.infrastructure.utils.RedisUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * @description 统一任务调度器
 * @author lanrunli
 *
 */
@Component
//@EnableScheduling
@Slf4j
public class SeamJobScheduler {

	@Autowired
	private IEhomeService ehomeService;

	@Autowired
	private IInventoryService inventoryService;

	@Autowired
	private RedisUtil redisUtil;

	@Autowired
	private IFaAssetService faAssetService;

	@Autowired
	private IFaFinanceService faFinanceService;

	@Autowired
	private IFaMatchService faMatchService;

	@Autowired
	private IEquipService equipService;


	/**
	 * @description 未盘点设备E家通知任务
	 */
	@Async
	@Scheduled(cron = "0 0 8 ? * MON-FRI")//周一至周五的8:00触发
	public void inventoryEhomeNoticeTask() {
		InetAddress addr = null;
		String redisJobKey = "Inventory-RedisLock-isRun";
		try {
            addr = InetAddress.getLocalHost();
            String ip = addr.getHostAddress();

            boolean lock = redisUtil.setIfAbsent(redisJobKey, ip, 30, TimeUnit.MINUTES);//30分钟过期
            if(lock) {
            	run();
            }else {
            	log.info("----------分布式锁已被占用，《未盘点E家通知》任务正在执行");
            }
        } catch (UnknownHostException e) {
            log.error("获取本地ip异常",e);
        }catch (Exception e) {
			log.error("未盘点E家通知异常",e);
		}finally {
			redisUtil.del(redisJobKey);//释放锁
		}
	}

	private void run() {
		log.info("----------未盘点E家通知开始");
		List<Inventory> list = inventoryService.findInventoryEhomeNoticeList();

		if(CollectionUtils.isNotEmpty(list)) {
			String content = "盘点通知：您有新的盘点任务，待盘点设备【%s】台，请进入资产管家应用的易盘点功能完成反馈确认，谢谢！";
			for (Inventory inventory : list) {
				ehomeService.pushText(String.format(content, inventory.getMemo()), inventory.getUserCode());
			}
			String userCodeListStr = list.stream().map(Inventory::getUserCode).collect(Collectors.joining(","));
			log.info("----------未盘点E家通知结束,此次通知人：{}",userCodeListStr);
		}else {
			log.info("----------未盘点E家通知结束，无通知数据");
		}
	}

	/**
	 * @description 定时同步设备折旧数据任务
	 */
	@Async
	@Scheduled(cron = "0 0 23 4 * ?")//每月4日的23:00触发
	public void updateFaAssetTask() {
		InetAddress addr = null;
		String redisJobKey = "FaAsset-RedisLock-isRun";
		try {
            addr = InetAddress.getLocalHost();
            String ip = addr.getHostAddress();
            boolean lock = redisUtil.setIfAbsent(redisJobKey, ip, 1, TimeUnit.HOURS);
            if(lock) {
            	faAssetService.updateFaAsset();
            }else {
            	log.info("----------分布式锁已被占用，《同步固定资产设备折旧数据》任务正在执行");
            }
        } catch (UnknownHostException e) {
            log.error("获取本地ip异常",e);
        }catch (Exception e) {
			log.error("同步《固定资产设备折旧数据》异常",e);
		}finally {
			redisUtil.del(redisJobKey);//释放锁
		}
	}

	/**
	 * @description 定时扫描财务系统转固设备
	 */
	@Async
	@Scheduled(cron = "0 0 0 * * ?")//每日的00:00触发
	public void updateFaFinanceTask() {
		InetAddress addr = null;
		String redisJobKey = "FaFinance-RedisLock-isRun";
		try {
            addr = InetAddress.getLocalHost();
            String ip = addr.getHostAddress();
            boolean lock = redisUtil.setIfAbsent(redisJobKey, ip, 3, TimeUnit.HOURS);
            if(lock) {
            	faFinanceService.addFaFinanceList();
            }else {
            	log.info("----------分布式锁已被占用，《扫描财务系统转固设备》任务正在执行");
            }
        } catch (UnknownHostException e) {
            log.error("获取本地ip异常",e);
        }catch (Exception e) {
			log.error("同步《扫描财务系统转固设备》异常",e);
		}finally {
			redisUtil.del(redisJobKey);//释放锁
		}
	}

	/**
	 * @description 定时扫描财务系统转固设备相符
	 */
	@Async
	@Scheduled(cron = "0 0 0 * * ?")//每日的00:00触发
	public void updateFaMatchTask() {
		InetAddress addr = null;
		String redisJobKey = "FaMatch-RedisLock-isRun";
		try {
            addr = InetAddress.getLocalHost();
            String ip = addr.getHostAddress();
            boolean lock = redisUtil.setIfAbsent(redisJobKey, ip, 3, TimeUnit.HOURS);
            if(lock) {
            	faMatchService.addFaMatch();
            }else {
            	log.info("----------分布式锁已被占用，《定时扫描财务系统转固设备相符》任务正在执行");
            }
        } catch (UnknownHostException e) {
            log.error("获取本地ip异常",e);
        }catch (Exception e) {
			log.error("同步《定时扫描财务系统转固设备相符》异常",e);
		}finally {
			redisUtil.del(redisJobKey);//释放锁
		}
	}

//	/**
//	 * @description 设备卡片责任人变动通知
//	 */
//	@Scheduled(cron = "0 0/5 * * * ?")//每日的00:00触发
//	public void equipAlterNoticeTask() {
//		InetAddress addr = null;
//		String redisJobKey = "EquipAlterNotice-RedisLock-isRun";
//		try {
//            addr = InetAddress.getLocalHost();
//            String ip = addr.getHostAddress();
//            boolean lock = redisUtil.setIfAbsent(redisJobKey, ip, 5, TimeUnit.MINUTES);
//            if(lock) {
//
//            	//do to
//				List<String> equipCodes = equipService.findAllEquipCode();
//				equipService.validatedEquipUserAlterNotice(equipCodes);
//				for(String equipCode:equipCodes) {
//
//				}
//            	List<EquipUserAlterNotice> list = equipService.findEquipUserAlterNoticeList();
//			//	List<EquipUserAlterNotice> list = groupingByEquipCode(lists);
//            	String contentTemp = "你好，设备卡片【%s】于【%s】更新至你名下，如有疑问可咨询该设备的部门管理员：【%s】，详情亦可通过e家APP进入资产管家应用查看‘我的设备’";
//            	String urlTemp = "http://a.aa?target=device&deviceId=%s&identity=com.csair.seam";
//            	if(CollectionUtils.isNotEmpty(list)) {
//        			for (EquipUserAlterNotice equipUserAlterNotice : list) {
//        				String content = String.format(contentTemp, equipUserAlterNotice.getEquipCode(),equipUserAlterNotice.getModifiedtime(),equipUserAlterNotice.getManagerName());
////        				NoticeResult result = ehomeService.pushText(content, equipUserAlterNotice.getUserCode());
//        				String url = String.format(urlTemp, equipUserAlterNotice.getEquipCode());
//        				NoticeResult result = ehomeService.pushRichText("资产更新通知", content, url, "设备详情", equipUserAlterNotice.getUserCode());
//        				if(result != null && result.getCode() == 0) {
//        					equipService.updateEquipUserAlterNotice(equipUserAlterNotice.getId());
//        				}
//					}
//        			String userCodeListStr = list.stream().map(EquipUserAlterNotice::getUserCode).collect(Collectors.joining(","));
//        			log.info("----------设备卡片责任人变动通知结束,此次通知人：{}",userCodeListStr);
//        		}else {
//        			log.info("----------设备卡片责任人变动通知结束，无通知数据");
//        		}
//            }else {
//            	log.info("----------分布式锁已被占用，《设备卡片责任人变动通知》任务正在执行");
//            }
//        } catch (UnknownHostException e) {
//            log.error("获取本地ip异常",e);
//        }catch (Exception e) {
//			log.error("同步《设备卡片责任人变动通知》异常",e);
//		}finally {
//			redisUtil.del(redisJobKey);//释放锁
//		}
//	}

	/**
	 * @description 设备卡片责任人变动通知
	 */
	@Scheduled(cron = "0 0/30 * * * ?")//每日的00:00触发
	public void equipAlterNoticeTask() {
		InetAddress addr = null;
		String redisJobKey = "EquipAlterNotice-RedisLock-isRun";
		try {
			addr = InetAddress.getLocalHost();
			String ip = addr.getHostAddress();
			boolean lock = redisUtil.setIfAbsent(redisJobKey, ip, 5, TimeUnit.MINUTES);
			if(lock) {
				//do to
				String userCodeListStr = "";
				List<String> equipCodes = equipService.findAllEquipCode();
				if(equipCodes.isEmpty()){
					log.info("----------设备卡片责任人变动通知结束,此次通知人：{}");
					return;
				}
				equipService.validatedEquipUserAlterNotice(equipCodes);
				for(String equipCode:equipCodes) {
					List<EquipUserAlterNotice> list = equipService.findEquipUserAlterNoticeList(equipCode);
					if(list.isEmpty()){
						continue;
					}
					EquipUserAlterNotice equipUserAlterNotice = list.get(0);
					//	List<EquipUserAlterNotice> list = groupingByEquipCode(lists);
					String contentTemp = "你好，设备卡片【%s】于【%s】更新至你名下，如有疑问可咨询该设备的部门管理员：【%s】，详情亦可通过e家APP进入资产管家应用查看‘我的设备’";
					String urlTemp = "http://a.aa?target=device&deviceId=%s&identity=com.csair.seam";
					String content = String.format(contentTemp, equipUserAlterNotice.getEquipCode(),equipUserAlterNotice.getModifiedtime(),equipUserAlterNotice.getManagerName());
//        				NoticeResult result = ehomeService.pushText(content, equipUserAlterNotice.getUserCode());
					String url = String.format(urlTemp, equipUserAlterNotice.getEquipCode());
					NoticeResult result = ehomeService.pushRichText("资产更新通知", content, url, "设备详情", equipUserAlterNotice.getUserCode());
					if(result != null && result.getCode() == 0) {
						equipService.updateEquipUserAlterNoticeByEquipCode(equipCode);
					}
					userCodeListStr = equipUserAlterNotice.getUserCode()+",";
				}
				log.info("----------设备卡片责任人变动通知结束,此次通知人：{}",StringUtils.isEmpty(userCodeListStr)?"无":userCodeListStr);
			}else {
				log.info("----------分布式锁已被占用，《设备卡片责任人变动通知》任务正在执行");
			}
		} catch (UnknownHostException e) {
			log.error("获取本地ip异常",e);
		}catch (Exception e) {
			log.error("同步《设备卡片责任人变动通知》异常",e);
		}finally {
			redisUtil.del(redisJobKey);//释放锁
		}
	}


	private static List<EquipUserAlterNotice> groupingByEquipCode(List<EquipUserAlterNotice> persons) {
		List<EquipUserAlterNotice> re = new ArrayList();
		//分组
		Map<String, List<EquipUserAlterNotice>> groupBySex = persons.stream().collect(Collectors.groupingBy(EquipUserAlterNotice::getEquipCode));
		//遍历分组
		for (Map.Entry<String, List<EquipUserAlterNotice>> entryUser : groupBySex.entrySet()) {
			String key = entryUser.getKey();
			List<EquipUserAlterNotice> entryUserList = entryUser.getValue();
			entryUserList = removeDupliByUserCode(entryUserList);
			re.addAll(entryUserList);
		}
		re.stream().forEach(System.err::println);
		return re;
	}

	public static List<EquipUserAlterNotice> removeDupliByUserCode(List<EquipUserAlterNotice> persons) {
		Set<EquipUserAlterNotice> personSet = new TreeSet<>((o1, o2) -> o1.getUserCode().compareTo(o2.getUserCode()));
		personSet.addAll(persons);
		return new ArrayList<>(personSet);
	}
}
